#include "ftp_client.h"

extern int terminate;
/*
sighandler:信号处理函数
sig:具体的信号值
返回值:
	无
*/
void sighandler(int sig)
{
	switch (sig)
	{
	case SIGINT:
		terminate = 1;
		break;
	}
}

/*
make_tcp_client:创建一个TCP客户端套接字
@IP  :连接服务器的地址
@port:连接服务器的端口号
返回值：
	tcp的连接套接字
*/
int make_tcp_client(const char *ip, unsigned short port)
{
	// 1.创建一个套接字
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (-1 == sockfd)
	{
		perror("create socket failed");
		exit(-1);
	}
	// 2.连接目标服务器
	struct sockaddr_in saddr;					   // 保存服务器的地址(IP+port)
	memset(&saddr, 0, sizeof(struct sockaddr_in)); // 清空结构体
	saddr.sin_family = AF_INET;
	inet_aton(ip, &saddr.sin_addr); // ip
	saddr.sin_port = htons(port);	// port
	int ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
	if (ret == -1)
	{
		perror(RED "connect error" RESET);
		exit(-1);
	}
	printf(GREEN "connect success\n" RESET);
	return sockfd;
}

/*--------------------------------------------------------------------------------------------------*/

/*
send_command:向服务器发送一个命令
@cmd_no    :命令号
@arg_1_data:命令参数
@arg_1_len :参数长度
返回值：
	无
*/
void send_command(int sockfd, enum CMD_NO cmd_no, char *arg_1_data, int arg_1_len)
{
	// 按照私有协议给服务器发送请求
	// 0xc0  pkg_len cmd_no arg_1_len arg_1_data(arg_1_len) arg_1_data(filename) 0xc0

	char cmd[1024] = {0}; // 表示发送的数据包
	int pkg_len = 4 + 4 + 4 + arg_1_len;
	int i = 0;
	// 0xc0
	cmd[i++] = 0xc0; // 包头
	// pkg_len
	cmd[i++] = pkg_len & 0xff; // 第一个字节(低字节) pkg_len
	cmd[i++] = (pkg_len >> 8) & 0xff;
	cmd[i++] = (pkg_len >> 16) & 0xff;
	cmd[i++] = (pkg_len >> 24) & 0xff;
	// cmd_no
	cmd[i++] = cmd_no & 0xff; // 第一个字节(低字节) cmd_no
	cmd[i++] = (cmd_no >> 8) & 0xff;
	cmd[i++] = (cmd_no >> 16) & 0xff;
	cmd[i++] = (cmd_no >> 24) & 0xff;
	// arg_1_len
	cmd[i++] = arg_1_len & 0xff; // 第一个字节(低字节) arg_1_len
	cmd[i++] = (arg_1_len >> 8) & 0xff;
	cmd[i++] = (arg_1_len >> 16) & 0xff;
	cmd[i++] = (arg_1_len >> 24) & 0xff;

	int j;
	for (j = 0; j < arg_1_len; j++)
	{
		cmd[i++] = arg_1_data[j];
	}
	// 包尾
	cmd[i++] = 0xc0;

	int ret = write(sockfd, cmd, i);
	if (ret != i)
	{
		printf(RED "send command failed!\n" RESET);
		return;
	}
}

/*
receive_response:接收服务器响应
@sockfd        :通信的套接字
@command_number:命令号
@recv_size     :数据包的回复的内容长度(如get file) recv_size为file中文件内容长度
返回值：
	无
*/
void receive_response(int sockfd, enum CMD_NO command_number, int *recv_size)
{
	//(1).0xc0  pkg_len(4) cmd_no(4) resp_len(4) result(1) resp_conent(filesize) 0xc0

	char cmd[1024] = {0};
	// 读取服务器发送给我的命令(按照协议读取数据),找到第一个0xc0(用户数据中不能出现0xc0)
	unsigned char ch;
	int r;
	do
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	} while (ch != 0xc0);

	// 防止上一次遗留的数据包的包尾
	while (ch == 0xc0)
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	}
	// ch肯定不是0xc0,是数据包中的第一个有效字节
	int i = 0;
	while (ch != 0xc0) // 一次性把数据包读取到cmd中
	{
		cmd[i++] = ch;
		read(sockfd, &ch, 1);
	}

	// 做一个简单的校验(数据包长度校验)
	int pkg_len = (cmd[0] & 0xff) | ((cmd[1] & 0xff) << 8) |
				  ((cmd[2] & 0xff) << 16) | ((cmd[3] & 0xff) << 24);
	if (i != pkg_len) // 读取到的实际长度和理论长短不一样,直接丢弃
	{
		printf(RED "pkg_len = %d,i = %d\n" RESET, pkg_len, i);
		return;
	}
	/*
		总结一下这个协议判断命令是否正确的方法：
		龙哥的：
				0xc0   数据  0xc0
				如果数据中出现0xc0 需要转义，
				约定:
					0xc0 ->0xdb 0xdc
					0xdb ->0xdb 0xdd  这是怕发送方发的就是0xdb 0xdd这两个数据，避免重复转
					这时0xdb 0xdd->		0xdb 0xdd 0xdd
		我写的这个：
		先获取一帧的包头0xc0，然后去获取包尾，如果数据中有0xc0比较实际长度和理论长短
		小于则丢掉获取下一帧，(我在想如果有杠精说数据中我就要有0xc0，这时我想就时实时比较，获取一个字节比较一次)
		直到相等。
	*/
	// 解析命令号,根据命令号去解析剩下的参数
	enum CMD_NO cmd_no = (cmd[4] & 0xff) | ((cmd[5] & 0xff) << 8) |
						 ((cmd[6] & 0xff) << 16) | ((cmd[7] & 0xff) << 24);
	if (cmd_no != command_number)
	{
		printf(RED "cmd_no = %d\n" RESET, cmd_no);
		return;
	}

	if (cmd[12] != 0) // 如果获取失败,解析服务器的错误码
	{
		printf("Command failed!\n");
		int errnum = (cmd[13] & 0xff) | ((cmd[14] & 0xff) << 8) |
					 ((cmd[15] & 0xff) << 16) | ((cmd[16] & 0xff) << 24);
		printf(RED "errno = %d\n" RESET, errnum);
	}
	else // 获取成功,解析命令的结果内容
	{
		if (recv_size != NULL) // 命令号后带参数
		{
			*recv_size = (cmd[13] & 0xff) | ((cmd[14] & 0xff) << 8) |
						 ((cmd[15] & 0xff) << 16) | ((cmd[16] & 0xff) << 24);
		}
		else // 命令号后不带参数
		{
			printf(GREEN "%s\n" RESET, cmd + 13);
		}
	}
}
/*--------------------------------------------------------------------------------------------------*/

/*
cmd_ls:处理用户的ls请求
@sockfd:客户端的套接字描述符,用来和服务器进行通信
返回值:
	无
*/
void cmd_ls(int sockfd)
{
	send_command(sockfd, FTP_CMD_LS, NULL, 0);
	receive_response(sockfd, FTP_CMD_LS, NULL);
}
/*
cmd_get:处理客户端的get请求
@sockfd:客户端的套接字描述符,用来和服务器进行通信
@filename:客户端相要获取的文件名

返回值:
	无
*/
void cmd_get(int sockfd, char *filename)
{
	send_command(sockfd, FTP_CMD_GET, filename, strlen(filename));
	int recv_size;
	receive_response(sockfd, FTP_CMD_GET, &recv_size);
	FILE *fp = fopen(filename, "w+");
	if (fp == NULL)
	{
		perror(RED "cmd_get:fopen file failed!\n" RESET);
		return;
	}
	int cur_read = 0;
	while (cur_read < recv_size)
	{
		unsigned char buf[1024] = {0};
		int r = read(sockfd, buf, 1024);
		if (r > 0)
		{
			cur_read += r;
			fwrite(buf, 1, r, fp);
		}
	}
	fclose(fp);
}

/*
cmd_get_folder:get下载文件夹
@sockfd:客户端的套接字描述符,用来和服务器进行通信
@folder_path:客户端相要获取的文件夹路径
*/
void cmd_get_folder(int sockfd, char *folder_path)
{
	send_command(sockfd, FTP_CMD_GET_FOLDER, folder_path, strlen(folder_path));
	// 接收文件夹的响应
	int recv_size;
	receive_response(sockfd, FTP_CMD_GET_FOLDER, &recv_size);
	// 目标文件夹不存在时创建
	if (opendir(folder_path) == NULL)
	{
		mkdir(folder_path, 0777);
	}
	// 进入文件夹
	chdir(folder_path);
	char path[1024] = {0};
	getcwd(path, 1024);
	int s = strlen(path);
	while (1)
	{
		struct
		{
			unsigned char filename[128];
			unsigned int file_size;
		} tmp;
		memset(&tmp, 0, sizeof(tmp));
		// 接收文件名
		read(sockfd, &tmp, sizeof(tmp));
		sprintf(path + s, "/%s", tmp.filename);
		unsigned int size = tmp.file_size;
		printf("---path：%s---\n", path);
		printf("---size:%d---\n", size);

		FILE *fp = fopen(path, "w+");
		if (fp == NULL)
		{
			perror("cmd_get:fopen file failed!\n");
			return;
		}
		int cur_read = 0;
		while (cur_read < size)
		{
			unsigned char buf[128] = {0};
			int r = read(sockfd, buf, 128);
			if (r > 0)
			{
				cur_read += r;
				fwrite(buf, 1, r, fp);
			}
		}
		fclose(fp);
	}
}

/*
cmd_get:处理客户端的put请求
@sockfd:客户端的套接字描述符,用来和服务器进行通信
@filename:客户端相要推送的文件名
返回值:
	无
*/
void cmd_put(int sockfd, char *filename)
{
	// 0xc0  pkg_len cmd_no arg_1_len arg_1_data(filename) arg_1_data2(filesize) 0xc0
	char cmd[1024] = {0}; // 表示发送的数据包
	// 获取文件大小
	struct stat st;
	int r = lstat(filename, &st);
	if (r == -1)
	{
		perror(RED "cmd_put lstat failed!" RESET);
		return;
	}
	int arg_1_len = strlen(filename); // 参数长度
	int pkg_len = 4 + 4 + 4 + arg_1_len + 4;
	enum CMD_NO cmd_no = FTP_CMD_PUT;
	int file_size = st.st_size;

	int i = 0;
	// 0xc0
	cmd[i++] = 0xc0; // 包头
	// pkg_len
	cmd[i++] = pkg_len & 0xff; // 第一个字节(低字节) pkg_len
	cmd[i++] = (pkg_len >> 8) & 0xff;
	cmd[i++] = (pkg_len >> 16) & 0xff;
	cmd[i++] = (pkg_len >> 24) & 0xff;
	// cmd_no
	cmd[i++] = cmd_no & 0xff; // 第一个字节(低字节) cmd_no
	cmd[i++] = (cmd_no >> 8) & 0xff;
	cmd[i++] = (cmd_no >> 16) & 0xff;
	cmd[i++] = (cmd_no >> 24) & 0xff;
	// arg_1_len
	cmd[i++] = arg_1_len & 0xff; // 第一个字节(低字节) cmd_no
	cmd[i++] = (arg_1_len >> 8) & 0xff;
	cmd[i++] = (arg_1_len >> 16) & 0xff;
	cmd[i++] = (arg_1_len >> 24) & 0xff;
	// 文件名
	int j;
	for (j = 0; j < arg_1_len; j++)
	{
		cmd[i++] = filename[j];
	}
	// 文件大小
	cmd[i++] = file_size & 0xff; // 第一个字节(低字节) cmd_no
	cmd[i++] = (file_size >> 8) & 0xff;
	cmd[i++] = (file_size >> 16) & 0xff;
	cmd[i++] = (file_size >> 24) & 0xff;
	// 包尾
	cmd[i++] = 0xc0;
	int ret = write(sockfd, cmd, i);
	if (ret != i)
	{
		printf(RED "cmd_put send failed!\n" RESET);
		return;
	}

	memset(cmd, 0, sizeof(cmd));
	// 读取服务器发送给我的命令(按照协议读取数据),找到第一个0xc0(用户数据中不能出现0xc0)
	unsigned char ch;
	do
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	} while (ch != 0xc0);
	// 防止上一次遗留的数据包的包尾
	while (ch == 0xc0)
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	}
	// ch肯定不是0xc0,是数据包中的第一个有效字节
	i = 0;
	while (ch != 0xc0) // 一次性把数据包读取到cmd中
	{
		cmd[i++] = ch;
		read(sockfd, &ch, 1);
	}
	// 做一个简单的校验(数据包长度校验)
	pkg_len = (cmd[0] & 0xff) | ((cmd[1] & 0xff) << 8) |
			  ((cmd[2] & 0xff) << 16) | ((cmd[3] & 0xff) << 24);
	if (i != pkg_len) // 读取到的实际长度和理论长短不一样,直接丢弃
	{
		printf(RED "pkg_len = %d,i = %d\n" RESET, pkg_len, i);
		return;
	}
	// 解析命令号,根据命令号去解析剩下的参数
	cmd_no = (cmd[4] & 0xff) | ((cmd[5] & 0xff) << 8) |
			 ((cmd[6] & 0xff) << 16) | ((cmd[7] & 0xff) << 24);
	if (cmd_no != FTP_CMD_PUT)
	{
		printf(RED "cmd_no = %d\n" RESET, cmd_no);
		return;
	}
	if (cmd[12] != 0) // 如果获取失败,解析服务器的错误码
	{
		printf(RED "Command failed!\n" RESET);
		int errnum = cmd[12];
		printf(RESET "errno = %d\n" RESET, errnum);
	}
	else // 获取成功,表示服务端已经准备接收文件
	{
		// 发送文件的所有的内容
		FILE *fp = fopen(filename, "r");
		if (NULL == fp)
		{
			perror(RED "cmd_put fopen error" RESET);
			return;
		}
		unsigned char buf[1024] = {0};
		while (1) // 循环发送内容
		{
			memset(buf, 0, 1024);
			size_t r = fread(buf, 1, 1024, fp);
			if (r > 0)
			{
				write(sockfd, buf, r);
			}
			else if (r == 0)
			{
				break;
			}
			else
			{
				perror(RED "cmd_put fread error" RESET);
				break;
			}
		}
		fclose(fp);
	}
}

/*
cmd_bye:处理客户端的bye请求
@sockfd:客户端的套接字描述符,用来和服务器进行通信
返回值:
	无
*/
void cmd_bye(int sockfd)
{
	send_command(sockfd, FTP_CMD_BYE, NULL, 0);
}

/*
cmd_rm:处理客户端的rm请求
@filename:客户端相要推送的文件名
返回值:
	无
*/
void cmd_rm(int sockfd, char *filename)
{
	send_command(sockfd, FTP_CMD_RM, filename, strlen(filename));
	char cmd[1024] = {0};
	// 读取服务器发送给我的命令(按照协议读取数据),找到第一个0xc0(用户数据中不能出现0xc0)
	unsigned char ch;
	int r;
	do
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	} while (ch != 0xc0);

	// 防止上一次遗留的数据包的包尾
	while (ch == 0xc0)
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	}
	// ch肯定不是0xc0,是数据包中的第一个有效字节
	int i = 0;
	while (ch != 0xc0) // 一次性把数据包读取到cmd中
	{
		cmd[i++] = ch;
		read(sockfd, &ch, 1);
	}
	// 做一个简单的校验(数据包长度校验)
	int pkg_len = (cmd[0] & 0xff) | ((cmd[1] & 0xff) << 8) |
				  ((cmd[2] & 0xff) << 16) | ((cmd[3] & 0xff) << 24);
	if (i != pkg_len) // 读取到的实际长度和理论长短不一样,直接丢弃
	{
		printf(RED "pkg_len = %d,i = %d\n" RESET, pkg_len, i);
		return;
	}
	// 解析命令号,根据命令号去解析剩下的参数
	enum CMD_NO cmd_no = (cmd[4] & 0xff) | ((cmd[5] & 0xff) << 8) |
						 ((cmd[6] & 0xff) << 16) | ((cmd[7] & 0xff) << 24);
	if (cmd_no != FTP_CMD_RM)
	{
		printf(RED "cmd_no = %d\n" RESET, cmd_no);
		return;
	}
	if (cmd[12] != 0) // 如果获取失败,解析服务器的错误码
	{
		printf(RED "Command failed!\n" RESET);
		int errnum = cmd[12];
		printf(RED "errno = %d\n" RESET, errnum);
		printf(RED "No such file or directory\n" RESET);
	}
	else // 获取成功,解析命令的结果内容
	{
		// printf("cd success!\n");
		system(RED "cowsay \"rm success!\"" RESET);
	}
}

/*
cmd_cd:处理客户端的bye请求
@sockfd:客户端的套接字描述符,用来和服务器进行通信
@filename:要cd的那个的那个目录
返回值:
	无
*/
void cmd_cd(int sockfd, char *filename)
{
	send_command(sockfd, FTP_CMD_CD, filename, strlen(filename));
	//(1).0xc0  pkg_len(4) cmd_no(4) resp_len(4) result(1) 0xc0
	char cmd[1024] = {0};
	// 读取服务器发送给我的命令(按照协议读取数据),找到第一个0xc0(用户数据中不能出现0xc0)
	unsigned char ch;
	int r;
	do
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	} while (ch != 0xc0);

	// 防止上一次遗留的数据包的包尾
	while (ch == 0xc0)
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	}
	// ch肯定不是0xc0,是数据包中的第一个有效字节
	int i = 0;
	while (ch != 0xc0) // 一次性把数据包读取到cmd中
	{
		cmd[i++] = ch;
		read(sockfd, &ch, 1);
	}

	// 做一个简单的校验(数据包长度校验)
	int pkg_len = (cmd[0] & 0xff) | ((cmd[1] & 0xff) << 8) |
				  ((cmd[2] & 0xff) << 16) | ((cmd[3] & 0xff) << 24);
	if (i != pkg_len) // 读取到的实际长度和理论长短不一样,直接丢弃
	{
		printf(RED "pkg_len = %d,i = %d\n" RESET, pkg_len, i);
		return;
	}
	// 解析命令号,根据命令号去解析剩下的参数
	enum CMD_NO cmd_no = (cmd[4] & 0xff) | ((cmd[5] & 0xff) << 8) |
						 ((cmd[6] & 0xff) << 16) | ((cmd[7] & 0xff) << 24);
	if (cmd_no != FTP_CMD_CD)
	{
		printf(RED "cmd_no = %d\n" RESET, cmd_no);
		return;
	}
	if (cmd[12] != 0) // 如果获取失败,解析服务器的错误码
	{
		printf(RED "Command failed!\n" RESET);
		int errnum = cmd[12];
		printf("errno = %d\n" RESET, errnum);
		printf(RED "No such file or directory\n" RESET);
	}
	else // 获取成功,解析命令的结果内容
	{
		// printf("cd success!\n");
		system("cowsay \"cd success!\"");
	}
}
/*
cmd_pwd:处理客户端的pwd请求
@sockfd:客户端的套接字描述符,用来和服务器进行通信
返回值:
	无
*/
/*
cmd_pwd:处理客户端的pwd请求
@sockfd:客户端的套接字描述符,用来和服务器进行通信
返回值:
	无
*/
void cmd_pwd(int sockfd)
{
	// 发送pwd请求到服务器
	char cmd[1024] = {0}; // 表示数据包
	int pkg_len = 8;
	enum CMD_NO cmd_no = FTP_CMD_PWD;
	int i = 0;
	cmd[i++] = 0xc0; // 包头

	cmd[i++] = pkg_len & 0xff; // 第一个字节(低字节) pkg_len
	cmd[i++] = (pkg_len >> 8) & 0xff;
	cmd[i++] = (pkg_len >> 16) & 0xff;
	cmd[i++] = (pkg_len >> 24) & 0xff;

	cmd[i++] = cmd_no & 0xff; // 第一个字节(低字节) cmd_no
	cmd[i++] = (cmd_no >> 8) & 0xff;
	cmd[i++] = (cmd_no >> 16) & 0xff;
	cmd[i++] = (cmd_no >> 24) & 0xff;

	cmd[i++] = 0xc0; // 包尾
	int r = write(sockfd, cmd, i);
	if (r != i)
	{
		printf("send pwdcmd failed!\n");
		return;
	}

	memset(cmd,0,1024);
	// 读取服务器发送给我的命令(按照协议读取数据),找到第一个0xc0(用户数据中不能出现0xc0)
	unsigned char ch;
	do
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	} while (ch != 0xc0);

	// 防止上一次遗留的数据包的包尾
	while (ch == 0xc0)
	{
		r = read(sockfd, &ch, 1);
		if (r <= 0)
		{
			exit(0);
		}
	}
	// ch肯定不是0xc0,是数据包中的第一个有效字节
	i = 0;
	while (ch != 0xc0) // 一次性把数据包读取到cmd中
	{
		cmd[i++] = ch;
		read(sockfd, &ch, 1);
	}

	// 做一个简单的校验(数据包长度校验)
	pkg_len = (cmd[0] & 0xff) | ((cmd[1] & 0xff) << 8) |
			  ((cmd[2] & 0xff) << 16) | ((cmd[3] & 0xff) << 24);
	if (i != pkg_len) // 读取到的实际长度和理论长短不一样,直接丢弃
	{
		printf(RED "pkg_len = %d,i = %d\n" RESET, pkg_len, i);
		return;
	}
	// 解析命令号,根据命令号去解析剩下的参数
	cmd_no = (cmd[4] & 0xff) | ((cmd[5] & 0xff) << 8) |
						 ((cmd[6] & 0xff) << 16) | ((cmd[7] & 0xff) << 24);
	if (cmd_no != FTP_CMD_PWD)
	{
		printf(RED "cmd_no = %d\n" RESET, cmd_no);
		return;
	}
	if (cmd[8] != 0) // 如果获取失败,解析服务器的错误码
	{
		printf(RED "Command failed!\n" RESET);
		int errnum = cmd[8];
		printf("errno = %d\n" RESET, errnum);
	}
	else // 获取成功,解析命令的结果内容
	{
		char buf[128] = {0};
		r = read(sockfd, buf, 128);
		if (r > 0)
		{
			printf("%s\n", buf);
		}
	}
}

/*
client_login:用户客户端登录服务器
@sockfd:用户通信的socket套接字
返回值：
	无
*/
int client_login(int sockfd)
{
	struct ftplogin login;
	memset(&login, 0, sizeof(login));
	int attempts = 0;
	bool loggedIn = false;

	while (attempts < 3 && !loggedIn)
	{
		printf("please input:\n");
		printf("username:");
		scanf("%s", login.usr);
		char *pwd;
		pwd = getpass("password: "); // 隐藏密码，类似 用sudo命令需要输入密码时Linux隐藏
		strcpy(login.pwd, pwd);
		//  写到服务器去验证是否有记录(可以配合注册使用)
		int ret = write(sockfd, &login, sizeof(login));
		if (ret == -1)
		{
			perror("write error");
			return -1;
		}

		char buf[20] = {0};
		ret = read(sockfd, buf, 20);
		if (ret == -1)
		{
			perror("read error");
			return -1;
		}
		if (strncmp(buf, "OK", 2) == 0)
		{
			printf("Login successful ,welcome!\n");
			loggedIn = true;
		}
		else if (strncmp(buf, "NO", 2) == 0)
		{
			attempts++;
			printf("Login failed ,The user name or password is incorrect\n");
		}
		else if (strncmp(buf, "Not Found", strlen("Not Found")) == 0)
		{
			memset(buf, 0, 20);
			printf("用户不存在是否注册？(YES/NO)\n");
			scanf("%s", buf);
			if (strcmp(buf, "YES") == 0 || strcmp(buf, "yes") == 0 || strcmp(buf, "y") == 0)
			{
				write(sockfd, buf, sizeof(buf));
				sleep(3);
				printf("已注册成功,快去进行ftp文件传输吧!\n");
				loggedIn = true;
			}
			else
			{
				return -1;
			}
		}
	}
	if (!loggedIn)
	{
		printf(RED "登录次数超过限制!已退出...\n" RESET);
		system("cowsay \"已退出...\"");
		return -1;
	}
}